#ifndef __ADPM_TYPES_H__
#define __ADPM_TYPES_H__

#include "user.h"

#define ADPM_STR_LEN 64


#define ADPM_REGION_SHIFT 11
#define ADPM_REGION_SIZE (PAGE_SIZE << ADPM_REGION_SHIFT)

/* **********************************
 * allocator type define
 * **********************************/
struct adpm_dirty{
  struct rb_node node;
  long start_vir, end_vir;
};
//page stat
#define ADPM_PAGE_STAT_FREE 0
#define ADPM_PAGE_STAT_DIRT 1
#define ADPM_PAGE_STAT_INAC 2
#define ADPM_PAGE_STAT_ACTV 3

#define ADPM_PAGE_STAT_MASK 3

//page flag 1 means no swap
#define ADPM_PAGE_SWAP_FLAG   (1<<2)

//  ftab lock > lru_list_lock > rbtree_lock > page_lock > dirty_lock (to prevent the dead lock)
struct adpm_allocator{
  struct adpm_sb_info *sbi;
  unsigned long start_pfn;
  unsigned long virt_base;
  struct list_head free;
  spinlock_t free_lock;
  long nr_free;

  //active_list and inactive list
  spinlock_t lru_list_lock;
  struct list_head inact_list;
  long nr_inact_list;
  //-----------------------------
  struct list_head act_list;
  long nr_act_list;

  //dirty list
  spinlock_t dirty_list_lock;
  struct list_head dirty_list;
  long nr_dirty_list;

  //swap info
  long swap_line; //maybe time to swap
  long swap_low;  // must swap

  //for alloc dirty struct
  struct kmem_cache *dirty_struct_pool;
};


/* **********************************
 * base type define
 * **********************************/

struct adpm_sb_info {
  unsigned long phys_addr; /* local DRAM mempool phys addr*/
  unsigned long virt_addr; /* local DRAM mempool virt addr(generate by ioremap) */
  unsigned long size; /* local DRAM mempool size*/
  unsigned long nr_pages; /* totalpages */
};

struct adpm_vm_info{
  unsigned long vm_start;
  unsigned long vm_end;
  unsigned long vm_pgoff;
  unsigned long vm_flags;
  struct vm_area_struct *vma;
};

struct adpm_file_base_info{
  long id;
  long size;
  long version;
};

#define ADPM_FILE_MAGIC 19990424UL
struct adpm_client_file{
  unsigned long magic;
  char name[ADPM_STR_LEN];
  atomic_t open_cnt;
  atomic_t mmap_cnt;
  struct adpm_sb_info *sbi;

  spinlock_t pages_lock;
  struct rb_root pages;
  struct adpm_vm_info vminfo;
  
  //the hash lock is in the hash table
  struct hlist_node hash_head;
  struct adpm_file_base_info base_info;

  //dirty struct rbtree
  spinlock_t dirtys_lock;
  struct rb_root dirtys;
};

struct adpm_rmap{
  long unsigned addr;
  struct vm_area_struct *vma;
  pte_t *pt;
};

struct adpm_page{
  //for allocator use, can only be used by allocator with lock protect
  spinlock_t lru_lock;
  unsigned long flag;
  long dirty_cnt;
  struct list_head lru;
  //for swap use
  struct adpm_rmap rmap;

  //for file use
  struct rb_node vm_node;
  long vm_pgoff; //vm page off in a file
  struct adpm_client_file *f;
};



/* **********************************
 * type for server request
 * **********************************/

enum{
  ADPM_one_file_info,
};
struct adpm_server_one_file_info_req{
  unsigned long name_hash;
};
struct adpm_server_one_file_info_res{
  long status;
  long id;
  long size;
  long version;
};


struct adpm_server_req{
  long type;
  union{
    struct adpm_server_one_file_info_req one_file_info;
  };
}__attribute__((aligned(sizeof(long))));

struct adpm_server_res{
  union{
    struct adpm_server_one_file_info_res one_file_info;
  };
}__attribute__((aligned(sizeof(long))));



#endif
